package com.moyq5.permit.center.web;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.moyq5.mvc.framework.general.Body;
import com.moyq5.mvc.framework.general.Sorting;
import com.moyq5.mvc.framework.jackson.result.ListResult;
import com.moyq5.mvc.framework.utils.StringUtils;
import com.moyq5.permit.center.bean.entity.SysPermit;
import com.moyq5.permit.center.bean.enums.SysPlatform;
import com.moyq5.permit.center.bean.search.SysPermit4Search;
import com.moyq5.permit.center.feign.client.SysPermitFeign;

/**
 * shiro配置
 * @author Moyq5
 * @date 2018年9月19日
 */
@Configuration
public class ShiroConfiguration {

	@Value("#{ @environment['shiro.loginUrl'] ?: '/login.jsp' }")
    protected String loginUrl;

    @Value("#{ @environment['shiro.successUrl'] ?: '/' }")
    protected String successUrl;

    @Value("#{ @environment['shiro.unauthorizedUrl'] ?: null }")
    protected String unauthorizedUrl;

    @Value("${client.cors.origns}")
    private List<String> origins;
    
    @Autowired
    private SysPermitFeign permitFeign;
    
    @Autowired
    private ShiroLoginRealm loginRealm;
    @Autowired
    private ShiroCodeRealm codeRealm;
    
    @Bean
    public SessionsSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        Collection<Realm> realms = new ArrayList<Realm>();
        realms.add(loginRealm);
        realms.add(codeRealm);
        securityManager.setRealms(realms);
        return securityManager;
    }

	@Bean
	public ShiroFilterChainDefinition shiroFilterChainDefinition() {
		
		SysPermit4Search permit4s = new SysPermit4Search();
		permit4s.setPlatform(SysPlatform.AUTH);
		ListResult<SysPermit> listRst = permitFeign.list(new Body<SysPermit4Search, Sorting>(permit4s, new Sorting()));

		DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
	    //chainDefinition.addPathDefinition("/**", "anon");
	    chainDefinition.addPathDefinition("/login/**", "myAuthc");
	    chainDefinition.addPathDefinition("/admin/auth", "anon");
	    chainDefinition.addPathDefinition("/admin/login/**", "anon");
	    
	    listRst.getData().forEach(permit -> {
	    	if (!StringUtils.isEmpty(permit.getPath()) && !StringUtils.isEmpty(permit.getAuth())) {
	    		chainDefinition.addPathDefinition(permit.getPath(), permit.getAuth());
	    	}
	    });
	    
	    chainDefinition.addPathDefinition("/**", "myAuthc"); // all paths are managed via annotations
	    /*
	    chainDefinition.getFilterChainMap().forEach((path, auth) -> {
	    	System.out.println(path + "=" + auth);
	    });
	    */
	    // or allow basic authentication, but NOT require it.
	    // chainDefinition.addPathDefinition("/**", "authcBasic[permissive]"); 
	    return chainDefinition;
	}
	
	@Bean
	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager,
            ShiroFilterChainDefinition shiroFilterChainDefinition) {
		
		Map<String, Filter> filterMap = new LinkedHashMap<String, Filter>(); 
		filterMap.put("myAuthc", new ShiroFormFilter(origins));
		filterMap.put("myPerms", new ShiroPermissionsFilter());
		
		ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
		factoryBean.setSecurityManager(securityManager);
		factoryBean.setFilterChainDefinitionMap(shiroFilterChainDefinition.getFilterChainMap());
		factoryBean.setFilters(filterMap);
		factoryBean.setLoginUrl(loginUrl);
		factoryBean.setSuccessUrl(successUrl);
		factoryBean.setUnauthorizedUrl(unauthorizedUrl);
		
		return factoryBean;
	}
	
}
